package com.zenjava.zendeploy.win;

import zom.zenjava.zendeploy.ZenDeployException;
import zom.zenjava.zendeploy.model.ApplicationProfile;
import zom.zenjava.zendeploy.model.Dependency;
import zom.zenjava.zendeploy.model.DependencySet;

import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;

public class WinUacFriendlyFileMover
{
    private final static Logger LOGGER = Logger.getLogger(WinUacFriendlyFileMover.class.getName());

    public static void main(String[] args)
    {
        try
        {
            WinUacFriendlyFileMover mover = new WinUacFriendlyFileMover();
            mover.moveFiles(new File(args[0]), new File(args[1]));
        }
        catch (Exception e)
        {
            // todo need to handle this a lot better
            JOptionPane.showMessageDialog(null, "File installation failed: " + e);
        }
    }

    public void moveFilesUacFriendly(ApplicationProfile appProfile, File installDir, File srcDir)
            throws ZenDeployException
    {
        try
        {
            StringBuilder adminExecCommand = new StringBuilder()
                    .append(installDir.getAbsolutePath())
                    .append("\\admin-exec.exe");

            StringBuilder jreCommand = new StringBuilder("\"")
                    .append(installDir.getAbsolutePath())
                    .append("\\jre\\")
                    .append(appProfile.getJreReference().getVersion())
                    .append("\\bin\\javaw.exe")
                    .append("\"");

            StringBuilder params = new StringBuilder()
                    .append("-cp \".");
            for (DependencySet dependencySet : appProfile.getDependencySet())
            {
                for (Dependency dependency : dependencySet.getDependencies())
                {
                    params.append(";").append(installDir.getAbsolutePath()).append("\\app\\");
                    params.append(dependency.getId()).append("-").append(dependency.getVersion()).append(".jar");
                }
            }
            params.append("\" ").append(getClass().getName());
            params.append(" \"").append(srcDir.getAbsolutePath());
            params.append("\" \"").append(installDir.getAbsolutePath());
            params.append("\"");

            ProcessBuilder builder = new ProcessBuilder(
                    adminExecCommand.toString(), jreCommand.toString(), params.toString());
            Process p = builder.start();
            int result = p.waitFor();
            if (result != 0)
            {
                throw new ZenDeployException(String.format(
                        "Installation failed, the UAC friendly file move returned error code '%s'", result));
            }
        }
        catch (InterruptedException e)
        {
            throw new ZenDeployException("Error executing move with UAC permissions (process was interrupted)", e);
        }
        catch (IOException e)
        {
            throw new ZenDeployException("Error executing move with UAC permissions", e);
        }
    }

    public void moveFiles(File srcDir, File destDir) throws ZenDeployException
    {
        LOGGER.info(String.format("Installing files from '%s' to '%s'", srcDir, destDir));


       // move dependencies
        File srcAppDir = new File(srcDir, "app");
        File destAppDir = new File(destDir, "app");
        if (srcAppDir.exists())
        {
            File[] dependencies = srcAppDir.listFiles();
            for (File dependency : dependencies)
            {
                File destDependencyFile = new File(destAppDir, dependency.getName());
                if (destDependencyFile.exists())
                {
                    destDependencyFile.delete();
                }
                if (!dependency.renameTo(destDependencyFile))
                {
                    throw new ZenDeployException(String.format("Unable to move file '%s' to '%s'",
                            dependency.getName(), destAppDir.getAbsolutePath()));
                }
            }
        }

        // move dependencies
        File srcJreDir = new File(srcDir, "jre");
        File destJreDir = new File(destDir, "jre");
        if (srcJreDir.exists())
        {
            File[] jreDirs = srcJreDir.listFiles();
            for (File jreDir : jreDirs)
            {
                File targetDir = new File(destJreDir, jreDir.getName());
                if (targetDir.exists())
                {
                    targetDir.delete();
                }
                if (!jreDir.renameTo(targetDir))
                {
                    JOptionPane.showMessageDialog(null, "Failed to install JRE dir");
                    throw new ZenDeployException(String.format("Unable to move JRE installation '%s' to '%s'",
                            jreDir.getName(), targetDir.getAbsolutePath()));
                }
            }
        }

        // move app profile
        File srcAppProfile = new File(srcDir, "app-profile.xml");
        File destAppProfile = new File(destDir, srcAppProfile.getName());
        if (destAppProfile.exists())
        {
            destAppProfile.delete();
        }
        if (!srcAppProfile.renameTo(destAppProfile))
        {
            throw new ZenDeployException(String.format("Unable to move launch profile '%s' to '%s'",
                    srcAppProfile.getName(), destDir.getAbsolutePath()));
        }
    }
}
